# distribution/hw03/modAddableInteger.py        David MacQuigg  ece373  10/15/07

from modAddable import Addable

class AddableInteger(Addable):
    '''A default Addable class.'''

    def __init__(self, value=0):
        '''Make an AddableInteger from either a simple integer or another
        AddableInteger.

    >>> AI2 = AddableInteger(2)
    >>> AI2.getInteger().intValue()
    2
    >>> AI2a = AddableInteger(AI2)
    >>> AI2a.getInteger().intValue()
    2
    >>> AddableInteger(2.1)
    Traceback (most recent call last):
     - - -
    TypeError: Need a simple integer or an AddableInteger.
        '''
        if type(value) is int:
            self._value = Integer(value)
        elif type(value) is AddableInteger:
            self._value = Integer(value.getInteger().intValue())
        else:
            raise TypeError, "Need a simple integer or an AddableInteger."

    def setValue(self, value):
        if type(value) is not int:
            raise TypeError, "Must have an int."
        self._value = Integer(value)
        
    def __add__(self, other):                                         # [1]
        '''Produce a sum of the lhs and rhs objects, without changing either.
        Return the sum as an object of the same type.
        >>> print AI5 + AI6
        11
        '''
        if type(other) is not AddableInteger: return None
        return AddableInteger(self.getInteger().intValue()
                                    + other.getInteger().intValue())

    def __neg__(self):                                                # [2]
        '''Return the negative, without altering the original.
        >>> print -AI5
        -5
        '''
        return AddableInteger(-self.getInteger().intValue())

    def getInteger(self):
        '''Return the Integer which defines our value.'''
        return self._value

    def __str__(self):                                                # [3]
        '''Return the string value of this AddableInteger.
        >>> print AI5
        5
        >>> print 'AI6 = %s' % AI6
        AI6 = 6
        '''
        return self._value.__str__()


class Integer(object):
    '''Wrapper for a simple integer'''
    
    def __init__(self, value=0):
        '''Create an Integer'''
        if type(value) is not int:
            raise TypeError, "%s is not an integer." % value
        self._value = value

    def intValue(self):
        '''Return the integer value of this Integer.'''
        return self._value
    
    def __str__(self):
        '''Return a string representation of this Integer.'''
        return str(self._value)


if __name__ == '__main__':

    AI5 = AddableInteger(5)
    AI6 = AddableInteger(6)

    from doctest import testmod
    testmod(verbose=True)

''' Notes
[1] The __add__() method overrides the "+" operator, so we can use Polynomial
objects with that operator.

[2] The __neg__() method overrides the unary "-" operator.

[3] The __str__() method overrides the built in methods used by the 'print'
statement and by string formatting functions.
'''
